<?php
////////////////////////////////////////////////////////////////////////////
//                                                                        //
// NOTICE OF COPYRIGHT                                                    //
//                                                                        //
// Dean`s Office for Moodle                                               //
// Электронный деканат                                                    //
// <http://deansoffice.ru/>                                               //
//                                                                        //
// Copyright (C) 2008-2999  Alex Djachenko (Алексей Дьяченко)             //
// alex-pub@my-site.ru                                                    //
// Copyright (C) 2008-2999  Evgenij Cigancov (Евгений Цыганцов)           //
// Copyright (C) 2008-2999  Ilia Smirnov (Илья Смирнов)                   // 
// Copyright (C) 2008-2999  Mariya Rojayskaya (Мария Рожайская)           // 
//                                                                        //
// This program is free software: you can redistribute it and/or modify   //
// it under the terms of the GNU General Public License as published by   //
// the Free Software Foundation, either version 3 of the Licensen.        //
//                                                                        //
// This program is distributed in the hope that it will be useful,        //
// but WITHOUT ANY WARRANTY; without even the implied warranty of         //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          //
// GNU General Public License for more details.                           //
//                                                                        //
// You should have received a copy of the GNU General Public License      //
// along with this program.  If not, see <http://www.gnu.org/licenses/>.  //
//                                                                        //
////////////////////////////////////////////////////////////////////////////

/**
 * Здесь происходит объявление класса формы, 
 * на основе класса формы из плагина modlib/widgets. 
 * Подключается из init.php. 
 */

// Подключаем библиотеки
require_once('lib.php');
// подключаем библиотеку форм
$DOF->modlib('widgets')->webform();

/** Форма создания/редактирования шаблона урока
 * 
 */
class dof_im_acl_edit_acl_form extends dof_modlib_widgets_form
{
    /**
     * @var dof_control
     */
    protected $dof;
    
    protected function im_code()
    {
        return 'acl';
    }
    
    protected function storage_code()
    {
        return 'acl';
    }
    
    protected function workflow_code()
    {
        return $this->storage_code();
    }
    
    /**
     * @see parent::definition()
     */
    public function definition()
    {
        $this->dof       = $this->_customdata->dof;
        // id учебного потока (если расписание создается для потока)
        
        // создаем ссылку на HTML_QuickForm
        $mform =& $this->_form;

        //создаем заголовок формы
        $mform->addElement('header','formtitle', $this->dof->get_string('new_acl',$this->im_code()));
        
        // добавляем новый элемент в форму
        $myselect =& $mform->addElement('hierselect', 'plugin', $this->dof->get_string('plugintype',$this->im_code()).
        										'<br>'.$this->dof->get_string('plugincode',$this->im_code()) ,null,'<br>');
        // устанавливаем для него варианты ответа
        $select1 = array( 'im' => 'im', 
        				  'storage' => 'storage',
                          'workflow' => 'workflow', 
                          'sync' => 'sync', 
                          'modlib' => 'modlib', 
                          'core' => 'core');
        $select2 = $this->get_list_previous($select1);
        $myselect->setOptions(array($select1, $select2));
        
        // код задания
        $mform->addElement('text', 'code', $this->dof->get_string('code',$this->im_code()));
        $mform->setType('code', PARAM_TEXT);    
        // код задания
        $mform->addElement('text', 'objectid', $this->dof->get_string('objectid',$this->im_code()));
        $mform->setType('objectid', PARAM_INT);    
        // родительская мандата
        $mform->addElement('select', 'aclwarrantid', 
                $this->dof->get_string('warrant', $this->im_code()).':', $this->get_list_aclwarrants());
        $mform->setType('aclwarrantid', PARAM_INT); 
        // кнопки "сохранить" и "отмена"
        $this->add_action_buttons(true, $this->dof->modlib('ig')->igs('save'));
        // применение проверки ко всем элементам
        $mform->applyFilter('__ALL__', 'trim');        
    }
    
    /** Добавление дополнительльных полей формы и установка значений по умолчанию
     * после загрузки данных в форму (если происходит редактирование)
     * 
     * @return null
     */
    public function definition_after_data()
    {

    }
    
    /** Возвращает двумерный массив типов и
     * соответствующих им кодов плагинов
     * @param array $types - список подразделений
     * @return array список кодов плагина, соответствующих данному типу
     */
    private function get_list_previous($types)
    {
        $previous = array();
        if ( ! is_array($types) )
        {//получили не массив - это значит что в базен нет ни одного подразделения
            return $previous;
        }
        foreach ($types as $type)
        {// забиваем массив данными    
            $previous[$type] = $this->get_list_value($type);
            
        }
        return $previous;
    }
    
    /** Возвращает список кодов плагина по типу плагина
     * @param int $type - id подразделения
     * @return array список кодов
     */
    private function get_list_value($type)
    {
        $code = array();
        if ( $type == 'core' )
        {// для core одоно значение 'coer'
            $codes = array('core' => 'core');
        }else
        {
            $codes = $this->dof->plugin_list_dir($type);
        }    
        foreach ( $codes as $key=>$obj )
        {
            $code[$key] = $key; 
        }
        return $code;
    }
    
    /** Получить список родительских мандат
     */
    function get_list_aclwarrants()
    {
        // найдем неархивные мандаты, которые можно наследовать
        if ( ! $aclwarrants = $this->dof->storage('aclwarrants')->get_records(array('status' => array('draft','active'))) )
        {// таких нет - вернем пустой элемент
            return $this->dof_get_select_values();
        }
        $rez = array();
        foreach ( $aclwarrants as $aclwarrant )
        {
            // отыщем хозяина мандаты
            if ( ! empty($aclwarrant->linkptype) AND ! empty($aclwarrant->linkpcode) )
            {// хозяин плагин - выведем его имя
                $note = $this->dof->get_string('title', $aclwarrant->linkpcode, null, $aclwarrant->linkptype);
            }else
            {// мандата ядра
                $note = $this->dof->get_string('core',$this->im_code());
            }
            $rez[$aclwarrant->id] = $aclwarrant->name.'['.$aclwarrant->code.']('.$note.')';
            
        }
        
        // сортируем и возвращаем
        asort($rez);
        return $this->dof_get_select_values() + $rez;
        
    }
    
    /** Проверка данных формы
     * @param array $data - данные, пришедшие из формы
     * 
     * @todo добавить проверку пересечения времени с другими уроками. Выводить
     * текст ошибки в поле begintime, вместе со ссылкой на другой шаблон
     * @todo добавить проверку прав создания объектов в подразделении
     * 
     * @return array - массив ошибок, или пустой массив, если ошибок нет
     */
    function validation($data)
    {
        // создаем ссылку на HTML_QuickForm
        $mform =& $this->_form;
        
        $errors = array();
        
        // убираем лишние пробелы со всех полей формы
        $mform->applyFilter('__ALL__', 'trim');
        
        // Возвращаем ошибки, если они есть
        return $errors;
    }
    
    /** Обработать пришедшие из формы данные
     *
     * @return bool 
     */
    public function process()
    {
        // переменная, хранящая результат операции сохранения
        $result = true;
        if ( $this->is_cancelled() )
        {//ввод данных отменен - возвращаем на страницу просмотра шаблонов
            redirect($this->dof->url_im('acl','/warrantlist.php'));
        }
        if ( $this->is_submitted() AND $formdata = $this->get_data() )
        {
            
            dof_debugging('im/acl form.php. Запрещенный в im sgl-код. Вынести в storage', DEBUG_DEVELOPER);
            $acl = new object;
            
            $acl->plugintype   = $formdata->plugin[0];
            $acl->plugincode   = $formdata->plugin[1];
            $acl->code         = $formdata->code;
            $acl->objectid     = $formdata->objectid;
            $acl->aclwarrantid = $formdata->aclwarrantid;
            if ( ! $this->dof->storage('acl')->count_records_select("plugintype=? 
                                             AND plugincode=?
                                             AND code=? AND objectid=? 
                                             AND aclwarrantid=?",(array) $acl) )
            {// если такого права еще нет - добавим';
                $result = ($result AND (bool)$this->dof->storage('acl')->insert($acl));
            }
            if ( $result )
            {// если все успешно - делаем редирект
                redirect($this->dof->url_im('acl','/warrantacl.php?id='.$acl->aclwarrantid));
            }
            return $result;
        }
    } 
    
}

/** Форма для передачи своих полномочий другим пользователей
 *
 */
class dof_im_give_warrant_acl_form extends dof_modlib_widgets_form
{
    /**
     * @var dof_control
     */
    protected $dof;

    protected function im_code()
    {
        return 'acl';
    }

    protected function storage_code()
    {
        return 'acl';
    }

    protected function workflow_code()
    {
        return $this->storage_code();
    }

    /**
     * @see parent::definition()
     */
    public function definition()
    {
        global $DOF;
        $this->dof       = $this->_customdata->dof;
        $aclwarrantid    = $this->_customdata->aclwarrantid;
        $departmentid    = $this->_customdata->departmentid;
        $appointmentid   = $this->_customdata->appointmentid;
        $id              = $this->_customdata->id;
        $curperson       = $this->dof->storage('persons')->get_bu();
        
        $rules = array();
        
        // получаем массив прав по id доверенности
        if ($list = $DOF->storage('acl')->get_records(array(
                'aclwarrantid' => $aclwarrantid)))
        {
            foreach ($list as $rule)
            {
                $rules[] = array('value' =>$rule->plugintype.'_'.$rule->plugincode.'_'.$rule->code); 
            }
        }
        
        // создаем ссылку на HTML_QuickForm
        $mform =& $this->_form;

        //создаем заголовок формы
        $mform->addElement('header','formtitle', $this->dof->get_string('give_warrant',$this->im_code()));
        
        
        // hidden поля с id доверенности и департемента и назначения
        $mform->addElement('hidden', 'aclwarrantid', $aclwarrantid);
        $mform->addElement('hidden', 'departmentid', $departmentid);
        $mform->addElement('hidden', 'appointmentid', $appointmentid);
        $mform->addElement('hidden', 'curpersonid', $curperson->id);
        $mform->addElement('hidden', 'id', $id);
        
        // hidden поля с id персон
        $personids = '0';
        if (!empty($this->_customdata->personids))
        {
            $personids = implode('_', $this->_customdata->personids);
        }
        
        $mform->addElement('hidden', 'personids', $personids);
        
        $mform->addElement('text', 'warrantname', $this->dof->get_string('warrant_name',$this->im_code()), 
                array('maxlength' => '64', 'size' => '18'));
        
        $mform->addElement('text', 'warrantcode', $this->dof->get_string('warrant_code',$this->im_code()),
                array('maxlength' => '64', 'size' => '18'));
        
        $mform->addElement('textarea', 'warrantnote', $this->dof->get_string('warrant_notice',$this->im_code()),
                array('wrap' => 'virtual', 'cols' => '50', 'rows' => '10'));
        
        $mform->addElement('html', '<br/>');
        $mform->addElement('date_selector', 'warrantbegin', $this->dof->get_string('warrant_duration_begin',$this->im_code()));
        $mform->addElement('date_selector', 'warrantend', $this->dof->get_string('warrant_duration_end',$this->im_code()));
        
        $options = array('0' => $this->dof->get_string('warrant_regive_allow', $this->im_code()),
                '1' => $this->dof->get_string('warrant_regive_forbid', $this->im_code()));
        
        $mform->addElement('select', 'noextend', $this->dof->get_string('warrant_regive', $this->im_code()),
                $options);
        
        // таблица с правами-чекбоксами
        $mform->addElement('html', '<br/><br/><table width="70%" align="left">');
        $mform->addElement('html', '<caption><b>'.$this->dof->get_string('warrant_select_acls', $this->im_code()).
                '</b></caption>');
        
        $i = 0;
        foreach ($rules as $rule)
        {// в зависимости от стороны таблицы открываем или закрываем текущую строку
            $opentr = '';
            $shuttr = '</tr>';
            
            if ($i % 2 == 0)
            {
                $opentr = '<tr>';
                $shuttr = '';
            }
            
            $mform->addElement('html', $opentr);
            $mform->addElement('html', '<td>');
            $mform->addElement('checkbox', $rule['value'], '', "&nbsp;&nbsp;".$rule['value']);
            $mform->addElement('html', '</td>');
            $mform->addElement('html', $shuttr);
            $i++;
        }
        
        $mform->addElement('html', '<tr><td colspan="1" align="right">');
        $mform->addElement('submit', 'submit', $this->dof->get_string('warrant_submit', $this->im_code()));
        $mform->addElement('html', '</td></tr>');
        
        $mform->addElement('html', '</table>');
        
        //если есть id - заполняем форму данными для редактирования
        if ($id)
        {
            $warrant = new object();
            $warrant->warrantname = $this->_customdata->subwarrant['warrant']->name;
            $warrant->warrantcode = $this->_customdata->subwarrant['warrant']->code;
            $warrant->warrantnote = $this->_customdata->subwarrant['warrant']->description;
            $warrant->noextend = $this->_customdata->subwarrant['warrant']->noextend;
            
            $subrules = array();
            $subrules = $this->_customdata->subwarrant['acls'];
            
            // цикл по правам доверенности
            foreach ($rules as $rule)
            {// цикл по правам субдоверенности
                foreach ($subrules as $subrule)
                {// если совпадение - делаем чекбокс активным 
                    $value = $subrule->plugintype."_".$subrule->plugincode."_".$subrule->code;
                    
                    if ($rule['value'] == $value)
                    {
                        $warrant->$rule['value'] = '1';
                    }
                }
            }
            
            $this->set_data($warrant);
        }
     
    }
    
    /** Добавление дополнительльных полей формы и установка значений по умолчанию
     * после загрузки данных в форму (если происходит редактирование)
     *
     * @return null
     */
    public function definition_after_data()
    {
        return true;
    }
    
    /** Проверка данных формы
     * @param array $data - данные, пришедшие из формы
     *
     * @todo добавить проверку пересечения времени с другими уроками. Выводить
     * текст ошибки в поле begintime, вместе со ссылкой на другой шаблон
     * @todo добавить проверку прав создания объектов в подразделении
     *
     * @return array - массив ошибок, или пустой массив, если ошибок нет
     */
    public function validation($data)
    {
        // создаем ссылку на HTML_QuickForm
        $mform =& $this->_form;
    
        $errors = array();
    
        // убираем лишние пробелы со всех полей формы
        $mform->applyFilter('__ALL__', 'trim');
    
        // складываем чекбоксы в отдельный массив
        $flags = array();
        foreach ($data as $key => $value)
        {
            $tmp = explode('_', $key);
    
            if ($tmp[0] == 'im' OR $tmp[0] == 'storage' OR $tmp[0] == 'workflow' OR $tmp[0] == 'sync')
            {
                $flags[$key] = $value;
            }
        }
    
        // проводим проверку параметров
        if (!isset($data['warrantname']) OR empty($data['warrantname']))
        {
            $errors['warrantname'] = $this->dof->get_string('warrant_regive_error_name', $this->im_code());
    
        }else if (!isset($data['warrantcode']) OR empty($data['warrantcode']))
        {
            $errors['warrantcode'] = $this->dof->get_string('warrant_regive_error_code', 'acl');
    
        }else if (!isset($flags) OR empty($flags))
        {
            $errors['aclwarrantid'] = $this->dof->get_string('warrant_regive_error_flags', $this->im_code());
    
        }else if (!isset($data['warrantbegin']) OR empty($data['warrantbegin']))
        {
            $errors['warrantbegin'] = $this->dof->get_string('warrant_regive_error_datebegin', $this->im_code());
    
        }else if (!isset($data['warrantend']) OR empty($data['warrantend']))
        {
            $errors['warrantend'] = $this->dof->get_string('warrant_regive_error_dateend', $this->im_code());
    
        }else if ( ($data['warrantbegin'] - $data['warrantend']) == 0)
        {
            $errors['warrantend'] = $this->dof->get_string('warrant_regive_error_datematch', $this->im_code());
    
        }else if (!isset($data['personids']) OR empty($data['personids']))
        {
            $errors['personids'] = $this->dof->get_string('warrant_regive_error_personids', $this->im_code());
    
        }else if (!isset($data['aclwarrantid']) OR empty($data['aclwarrantid']))
        {
            $errors['aclwarrantid'] = $this->dof->get_string('warrant_regive_error_aclwarrantid', $this->im_code());
        }
    
        // Возвращаем ошибки, если они есть
        return $errors;
    }
    
    /** Обработать пришедшие из формы данные
     *
     * @return bool
     */
    public function process()
    {
        $mform =& $this->_form;
        
        $data = $this->get_data();
        
        // убираем лишние пробелы со всех полей формы
        $mform->applyFilter('__ALL__', 'trim');
        
        // складываем чекбоксы в отдельный массив
        $flags = array();
        foreach ($data as $key => $value)
        {
            $tmp = explode('_', $key);
        
            if ($tmp[0] == 'im' OR $tmp[0] == 'storage' OR $tmp[0] == 'workflow' OR $tmp[0] == 'sync')
            {
                $flags[$key] = $value;
            }
        }
        
        // проводим проверку параметров 
        if (!isset($data->warrantname) OR empty($data->warrantname))
        {
            return false;
        
        }else if (!isset($data->warrantcode) OR empty($data->warrantcode)) 
        {
            return false;
            
        }else if (!isset($flags) OR empty($flags))
        {
            return false;
        
        }else if (!isset($data->warrantbegin) OR empty($data->warrantbegin))
        {
            return false;
        
        }else if (!isset($data->warrantend) OR empty($data->warrantend))
        {
            return false;
        
        }else if (!isset($data->personids) OR empty($data->personids))
        {
            return false;
        
        }else if (!isset($data->aclwarrantid) OR empty($data->aclwarrantid))
        {
            return false;
        }
        
        // данные правильные, создаем новую доверенность в aclwarrants в случае, если
        // параметр id отсутствует, иначе обновляем существующую субдоверенность
        
        // формируем массив отмеченных прав
        $acls = array();
        
        foreach ($flags as $key => $flag)
        {
            $acl = new object();
            $tmp = explode('_', $key);
             
            $acl->plugintype = $tmp[0];
            $acl->plugincode = $tmp[1];
            $acl->code = $tmp[2];
            $acl->objectid = 0;
            $acls[] = $acl;
        }
        
        // доверенные лица
        $personids = explode('_', $data->personids);
        
        // создаем объект доверенного лица
        $obj = new object();
        $obj->baseptype = 'storage';
        $obj->basepcode = 'persons';
        $obj->basetype = 'record';
        $obj->begindate = $data->warrantbegin;
        $obj->datecreate = time();
        $obj->duration = $data->warrantend - $data->warrantbegin;
        $obj->noextend = $data->noextend;
        $obj->departmentid = $data->departmentid;
        
        if ($data->id)
        {// обновляем субдоверенность
            
            // дописываем id доверенности
            $obj->aclwarrantid = $data->id;
            
            // обновляем всех доверенных лиц (aclwarrantagentg)
            if ( ! $this->dof->im('acl')->apply_to_update_warrantagents($obj, $personids))
            {
                return false;
            }
            
            // обновляем права
            if (! $this->dof->storage('acl')->update_warrant_acls($data->id, $acls))
            {
                return false;
            }
        }else 
        {    
            // сначала доверенность
            $aclwarrant = new object();
            $aclwarrant->code = $data->warrantcode;
            $aclwarrant->name = $data->warrantname;
            $aclwarrant->parentid = '0';
            $aclwarrant->linkptype = 'storage';
            $aclwarrant->linkpcode = 'persons';
            $aclwarrant->linktype = 'record';
            $aclwarrant->linkid = $data->curpersonid;
            $aclwarrant->description = $data->warrantnote;
            $aclwarrant->noextend = $data->noextend;
            
            // не удалось записать доверенность - выходим из программы
            if (! $recid = $this->dof->storage('aclwarrants')->insert($aclwarrant))
            {
                return false;
            }
            else
            {// иначе меняем статус доверенности на активный
                $tmpobj = new object();
                $tmpobj->id = $recid;
                $tmpobj->status = 'active';
                $this->dof->storage('aclwarrants')->update($tmpobj);
            }
            
            // заносим права в таблицу acl
            if (! $this->dof->storage('acl')->add_warrant_acls($recid, $acls))
            {
                return false;
            }
            
            $obj->aclwarrantid = $recid;
            // пытаемся сохранить доверенных лиц
            if (! $this->apply_to_insert_warrantagents($obj, $personids))
            {
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * Сохранение доверенных лиц для переданных пользователей
     * @param object $warrantagent - объект с данными для таблицы warrantagents
     * @param object $persolist - массив с id персон
     * @return bool
     */
    public function apply_to_insert_warrantagents($aclwarrantid, $departmentid, $begindate, 
    		$enddate, $noextend, $personlist) 
    {
        $rez = true;
        if ( ! empty($personlist))
        {// если список не пустой
           foreach ($personlist as $personid)
           {// для каждой доверенности добавим применение
               $rez = $rez && $this->add_warrantagent($aclwarrantid, $departmentid, $begindate, 
               		          $enddate, $noextend, $personid);
           }
        }
        return $rez;
    }
    
    /**
     * Обновление субдоверенности для переданных пользователей
     * @param object $warrantagent - объект с данными для таблицы warrantagents
     * @param object $persolist - массив с id персон
     * @return bool
     */
    
    public function apply_to_update_warrantagents($aclwarrantid, $departmentid, $begindate, 
    		$enddate, $noextend, $personlist) 
    {
        $res = true;
        // массив доверенных лиц, использующих данную доверенность 
        if ( ! $warrantagents = $this->dof->storage('aclwarrantagents')->get_records(
                array('aclwarrantid' => $aclwarrantid, 'status' => array('draft', 'active'))))
        {// никто не нашелся - будет пустым
            $warrantagents = array();
        }
        if ( !empty($personlist) )
        {// если массив персон не пустой
            foreach ( $personlist as $personid )
            {// для каждой проверяем применения
                $match = false;
                foreach ( $warrantagents as $key => $warrantagent )
                {
                    if ( $warrantagent->personid == $personid )
                    {// приминения найдены - обновляем дынные доверенного лица
                        $obj = new object();
                        $obj->id = $warrantagent->id;
                        $obj->begindate = $begindate;
                        $obj->duration = $begindate - $enddate;
                        $obj->noextend = $noextend;
                        
                        $res = $this->dof->storage('aclwarrantagents')->update($obj) AND $res;
                        unset($warrantagents[$key]);
                        $match = true;
                    }   
                }
                if ( !$match )
                {// не найдено - значит новый warrantagent
                    $res = $this->add_warrantagent($aclwarrantid, $departmentid, $begindate,
                           $enddate, $noextend, $personid) AND $res;
                }
            }
        }
        // все необновленные записи в warrantagents отправляем в архив
        foreach ( $warrantagents as $warrantagent )
        {
            $res = $this->dof->workflow('aclwarrantagents')->change($warrantagent->id,'archive') AND $res;
        }
        return $res;
    }
    
    /**
     * Сохранение доверенного лица
     * @param object $warrantagent - объект с данными для таблицы warrantagents
     * @return bool
     */
    public function add_warrantagent($aclwarrantid, $departmentid, $begindate,
            $enddate, $noextend, $personid) 
    {
    	$rez = true;
    	
        $record = new object();
        $record->baseptype = 'storage';
        $record->basepcode = 'persons';
        $record->basetype = 'record';
        $record->aclwarrantid = $aclwarrantid;
        $record->departmentid = $departmentid;
        $record->begindate	  = $begindate;
        $record->datecreate	  = time();
        $record->duration 	  = $enddate - $begindate;
        $record->noextend	  = $noextend;
        $record->personid	  = $personid;
		$record->baseid		  = $personid;
		$record->basepcode	  = 'persons';
		
        if (! $pid = $this->dof->storage('aclwarrantagents')->add($record))
        {
        	$rez = false;
        }
        
        // получаем статусы пользователя и доверенности
        $perstat = $this->dof->storage('persons')->get_field(array('id' => $personid), 'status');
        $warstat = $this->dof->storage('aclwarrants')->get_field(array('id' => $aclwarrantid), 'status');
        
        // добавляем ту же запись, но с измененными basepcode и baseid
        $record->basepcode = 'departments';
        $record->baseid = $record->departmentid;
        
        if ( ! $did = $this->dof->storage('aclwarrantagents')->add($record))
        {
            $rez = false;
        }
        
        // если персона и доверенность активны - активируем доверенное лицо
        if ($perstat == 'normal' AND $warstat == 'active')
        {
            $rez = $rez && $this->dof->workflow('aclwarrantagents')->change($did,'active');
            $rez = $rez && $this->dof->workflow('aclwarrantagents')->change($pid,'active');
        }
        
    	return $rez;
    }
}

?>